<?php

namespace App\Logic;

use App\Library\Logic\BaseOrderLogic;
use App\Library\Requests\Order\OrderStorePagingRequest;
use App\Library\Requests\Store\StoreTjRequest;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;

class OrderLogic extends BaseOrderLogic
{
    /**
     * paging
     * @param OrderStorePagingRequest $request
     * @return array
     */
    public function paging(OrderStorePagingRequest $request): array
    {
        $builder = $this->builder();
        if (is_null($request->sortColumn)) $builder->orderByDesc('order.id');
        if (!is_null($request->startAt)) {
            $builder->where('date', '>=', $request->startAt);
            request()->offsetUnset('startAt');
        }
        if (!is_null($request->endAt)) {
            $builder->where('date', '<=', $request->endAt);
            request()->offsetUnset('endAt');
        }
        if (!is_null($request->status)) {
            $builder->where('order_status.status', $request->status);
            request()->offsetUnset('status');
        }
        if (!is_null($request->userMobile)) {
            $builder->where('user.mobile', $request->userMobile);
            request()->offsetUnset('userMobile');
        }
        if (!is_null($request->sellerMobile)) {
            $builder->where('user_seller.mobile', $request->sellerMobile);
            request()->offsetUnset('sellerMobile');
        }
        if (!is_null($request->statusEvaluate)) {
            $builder->where('order_status.status_service', 2)
                ->where('order_status.status_evaluate', $request->statusEvaluate);
            request()->offsetUnset('statusEvaluate');
        }
        $paginate = helpBuilder($builder, $request)->paginate($request->limit, $this->columns());
        foreach ($paginate->items() as $v) {
            $this->incomeDetail($v);
            $this->incomeDetail($v, 'seller');
            $this->unsetIncome($v->income);
            unset($v->id);
        }
        return paginate($paginate);
    }

    /**
     * sendPaging
     * @param OrderStorePagingRequest $request
     * @return array
     */
    public function sendPaging(OrderStorePagingRequest $request): array
    {
        return $request->all();
    }

    /**
     * index
     * @param StoreTjRequest $request
     * @return array
     */
    public static function tj(StoreTjRequest $request): array
    {
        $dateStr = 'complete_at is not null';
        if (!is_null($request->startAt)) $dateStr .= " && complete_at>='$request->startAt'";
        if (!is_null($request->endAt)) $dateStr .= " && complete_at<='$request->endAt'";
        $str = "cast(sum(if($dateStr,%s,0)) as double) as %s";
        $rewardStr = 'reward_price>0';

        return self::query()->leftJoin('order_income', 'order_income.order_id', 'order.id')->storeId(staff('storeId'))
            ->first([
                DB::raw('count(if(main_id=0 && complete_at is not null,true,null)) as mainCount'),
                DB::raw('count(if(main_id>0 && complete_at is not null,true,null)) as fillCount'),
                DB::raw('cast(sum(if(complete_at is not null,store_amount,0)) as double) as totalAmount'),
                DB::raw(sprintf($str, 'traffic_price', 'trafficPrice')),
                DB::raw(sprintf($str, 'project_price', 'projectPrice')),
                DB::raw(sprintf($str, 'store_amount', 'storeAmount')),
                DB::raw("count(if($dateStr,true,null)) as orderCount"),
                DB::raw('count(if(' . $rewardStr . ' && ' . $dateStr . ', true, null)) as rewardCount'),
                DB::raw('cast(sum(if(reward_price>0 && ' . $dateStr . ', reward_price, null)) as double) as rewardPrice'),
            ])->toArray();
    }

    /**
     * indexCount
     * @param string $type
     * @return int
     */
    public static function indexCount(string $type): int
    {
        $builder = OrderLogic::query()->leftJoin('order_status', 'order.id', 'order_status.order_id');
        if ($type === 'pending') $builder->whereIn('order_status.status', [2, 4]);
        else if ($type === 'servicing') $builder->where('order_status.status', 5);
        else if ($type === 'complete') $builder->whereBetween('order.complete_at', [now()->startOfDay()->toDateTimeString(), now()->endOfDay()->toDateTimeString()]);
        else if ($type === 'cancel') $builder->whereNotNull('pay_at')->whereNotNull('cancel_at');
        return $builder->storeId(staff('storeId'))->count();
    }

    /**
     * incomeDetail
     * @param Model $order
     * @param string $type
     * @return void
     */
    public function incomeDetail(Model $order, string $type = 'user'): void
    {
        $obj = $type . '_invite_obj';
        $objId = $type . '_invite_id';
        if (is_null($order->income)) return;
        else if ($order->income->$objId === 0) return;
        $order->income->$obj = l('user_type')[cache('userType:' . $order->income->$objId)]['key'];
        $obj = $type . '_invite_up_obj';
        $objId = $type . '_invite_up_id';
        if ($order->income->$objId === 0) return;
        $order->income->$obj = l('user_type')[cache('userType:' . $order->income->$objId)]['key'];
    }

    /**
     * columns
     * @param array|null $columns
     * @return array
     */
    public function columns(?array $columns = null): array
    {
        return array_merge([
            'order.id',
            'order_status.status',
            'order.serial_number',
            'title',
            'duration',
            'file_id',
            'real_name',
            'seller.serial_number as seller_number',
            'user_seller.mobile as seller_mobile',
            'user_dm.nickname',
            'user.mobile',
            'address_id',
            'main_id',
            'tail.name as tail_nickname',
            'tail.wechat',
            'tail_user.mobile as tail_mobile',
            'staff.nickname as staff_nickname',
            'start_at',
            'end_at',
            'real_start_at',
            'real_end_at',
            'set_out_start_at',
            'set_out_pre_at',
            'set_out_at',
            'order.created_at',
            'complete_at',
            'user_deleted_at',
            'special_weather',
            'send',
            'send_flag',
            'system',
            'tel_interceptor',
            'reward_at',
            'evaluate_at',
            'settlement_at',
            'refund_at',
            'order.pay_at',
            'cancel_at',
            'settlement_price',
            'refund_traffic_price',
            'refund_order_price',
            'refund_price',
            'discount_price',
            'traffic_type',
            'project_price',
            'order_price',
            'traffic_price',
            'pay_price',
            'cancel_reason',
            'reward_price',
            'fill_count',
            'fill_price',
            'sign_file_id',
            'report_count',
            'after_sale_count',
            'order.remark',
            'status_report',
            'status_after_sale',
            'status_update',
            'status_settlement',
        ], $columns ?? []);
    }

    /**
     * columns
     * @param array|null $with
     * @return Builder
     */
    public function builder(?array $with = null): Builder
    {
        return $this->newQuery()->with(array_merge(['income', 'address'], $with ?? []))
            ->leftJoin('order_status', 'order_status.order_id', 'order.id')
            ->leftJoin('seller', 'seller.user_id', 'order.seller_id')
            ->leftJoin('seller_dm', 'seller_dm.user_id', 'order.seller_id')
            ->leftJoin('user', 'user.id', 'order.user_id')
            ->leftJoin('user_dm', 'user_dm.user_id', 'order.user_id')
            ->leftJoin('user as user_seller', 'user_seller.id', 'order.seller_id')
            ->leftJoin('admin_dm as tail', 'tail.user_id', 'order.tail_id')
            ->leftJoin('user as tail_user', 'tail_user.id', 'tail.user_id')
            ->leftJoin('staff', 'staff.id', 'order.staff_id')
            ->leftJoin('payment', 'payment.order_id', 'order.id')->storeId(staff('storeId'))
            ->whereNotNull('order.pay_at');
    }

    /**
     * unsetIncome
     * @param Model|null $m
     * @return void
     */
    public function unsetIncome(Model|null $m): void
    {
        if (is_null($m)) return;
        unsetObject($m, [
            'id',
            'order_id',
            'user_invite_id',
            'user_invite_up_id',
            'seller_invite_id',
            'seller_invite_up_id',
            'surplus_amount',
            'platform_discount_allowance',
            'platform_amount',
            'seller_level_id',
            'created_at',
            'pay_at',
        ]);
    }
}
